/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sma;

import jade.core.AID;
import jade.core.Agent;
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.FailureException;
import jade.domain.FIPAAgentManagement.NotUnderstoodException;
import jade.domain.FIPAAgentManagement.RefuseException;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.FIPAException;
import jade.domain.FIPANames;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;
import jade.proto.AchieveREInitiator;
import jade.proto.AchieveREResponder;
import java.io.IOException;
import sma.ontology.AuxInfo;
import sma.ontology.Cell;
import sma.ontology.InfoAgent;

/**
 *
 * @author
 */
public class HarvesterAgent extends Agent{
    
    private AuxInfo info;

    private AID harvesterCoordinator;

 
    public HarvesterAgent() {
    }

    /**
    * A message is shown in the log area of the GUI
    * @param str String to show
    */
    private void showMessage(String str) {
        System.out.println(getLocalName() + ": " + str);
    }

    @Override
    protected void setup() {

        /**** Very Important Line (VIL) *********/
        this.setEnabledO2ACommunication(true, 1);
        /****************************************/

        // Register the agent to the DF
        ServiceDescription sd1 = new ServiceDescription();
        sd1.setType(UtilsAgents.HARVESTER_AGENT);
        sd1.setName(getLocalName());
        sd1.setOwnership(UtilsAgents.OWNER);
        DFAgentDescription dfd = new DFAgentDescription();
        dfd.addServices(sd1);
        dfd.setName(getAID());
        try {
          DFService.register(this, dfd);
          showMessage("Registered to the DF");
        }
        catch (FIPAException e) {
          System.err.println(getLocalName() + " registration with DF " + "unsucceeded. Reason: " + e.getMessage());
          doDelete();
        }

        // search HarvesterAgent Coordinator
//        ServiceDescription searchCriterion = new ServiceDescription();
//        searchCriterion.setType(UtilsAgents.HARVESTERCOORDINATOR_AGENT);
//        this.harvesterCoordinator = UtilsAgents.searchAgent(this, searchCriterion);
        // searchAgent is a blocking method, so we will obtain always a correct AID

       /**************************************************/
//        ACLMessage requestInicial = new ACLMessage(ACLMessage.REQUEST);
//        requestInicial.clearAllReceiver();
//        requestInicial.addReceiver(this.harvesterCoordinator);
//        requestInicial.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
//        showMessage("Message OK");
//        try {
//          requestInicial.setContent("Initial request");
//          showMessage("Content OK" + requestInicial.getContent());
//        } catch (Exception e) {
//          e.printStackTrace();
//        }

        //we add a behaviour that sends the message and waits for an answer
//        this.addBehaviour(new HarvesterAgent.RequesterBehaviour(this, requestInicial));
        
        MessageTemplate mt = MessageTemplate.MatchProtocol(UtilsAgents.PROTOCOL_TURN);
        this.addBehaviour(new HarvesterAgent.QueriesReceiver(this, mt));

        // setup finished. When we receive the last inform, the agent itself will add
        // a behaviour to send/receive actions
    } //endof setup
    
    class QueriesReceiver extends AchieveREResponder {

        /* (non-Javadoc)
         * @see jade.proto.AchieveREResponder#prepareResponse(jade.lang.acl.ACLMessage)
         */
        @Override
        protected ACLMessage prepareResponse(ACLMessage arg0) throws NotUnderstoodException, RefuseException {
                ACLMessage response = arg0.createReply();

                try {
                        if (arg0.getContentObject() instanceof AuxInfo) {
                                response.setPerformative(ACLMessage.AGREE);
                                info = (AuxInfo) arg0.getContentObject();
                                showMessage("New turn " + info.toString());

        //			manageScouts(this.myAgent);
                        } else if (arg0.getPerformative() == ACLMessage.AGREE) {
                                response = null;
                        } else {
                                throw new NotUnderstoodException("Not the expected object type");
                        }
                } catch (UnreadableException e) {
                        response.setPerformative(ACLMessage.FAILURE);
                }
                 showMessage("Get information");
                return response;
        }

        /* (non-Javadoc)
         * @see jade.proto.AchieveREResponder#prepareResultNotification(jade.lang.acl.ACLMessage, jade.lang.acl.ACLMessage)
         */
        @Override
        protected ACLMessage prepareResultNotification(ACLMessage arg0, ACLMessage arg1) throws FailureException {
                return null;
        }

        /* (non-Javadoc)
         * @see jade.proto.AchieveREResponder#handleRequest(jade.lang.acl.ACLMessage)
         */
        @Override
        protected ACLMessage handleRequest(ACLMessage arg0) throws NotUnderstoodException, RefuseException {
                try {
                        Object objectReceived = arg0.getContentObject();
                        if (objectReceived instanceof AuxInfo) {
                                // Is the coordinator informing of a new turn
                                info = (AuxInfo) objectReceived;
                                showMessage("New turn received from coordinator: " + info.toString());

////                                 Find all my agents and send them the new turn
//                                ACLMessage message = new ACLMessage(ACLMessage.REQUEST);
//                                for (int x = 0; x < info.getMap().length; x++) {
//                                        for (int y = 0; y < info.getMap()[x].length; y++) {
//                                                Cell c = info.getCell(x, y);
//                                                if (c!=null)
//                                                        if (c.isThereAnAgent()) {
//                                                                InfoAgent a = c.getAgent();
//                                                                if (a.getAgent().equals("S")) {
//                                                                        message.addReceiver(a.getAID());
//                                                                }
//                                                        }
//                                        }
//                                }
//                                message.setProtocol(UtilsAgents.PROTOCOL_TURN);
//                                message.setSender(this.myAgent.getAID());
//                                message.setContentObject(info);//getInfo() added <---- :-D
//                                this.myAgent.send(message);
                        }

                } catch (UnreadableException e) {
                        showMessage("Received an Object that cannot be understood");
//                } catch (IOException e) {
//                        e.printStackTrace();
                } catch (Exception e) {
                        e.printStackTrace();
                }
                showMessage("Sent information");
                return super.handleRequest(arg0);
        }

        public QueriesReceiver(Agent arg0, MessageTemplate arg1) {
                super(arg0, arg1);
        }
    } // Endof QueriesReceiver
} // Endof HarvesterAgent
